home *** CD-ROM | disk | FTP | other *** search
- //==============================================================================
- // Scn20p2: AI Scenario Script for scenario 20 player 2
- //==============================================================================
- /*
- AI owner: Mike Kidd
- Scenario owner: Jeff Brown
-
- Overview:
- The player starts on the main continent, with a TC that converts to player 1.
- The CP is on a fortified island, and the player's goal is to capture the
- piece of Osiris that is on the island.
-
- The CP starts as Set (Vision) in the second age with Anubis (plague of serpents)
- as the minor god.
-
- The CP will choose Nephthys (ancestors, leviathan, scorpion man) for age 3,
- and Thoth (meteor, phoenix, sea turtle) for age 4.
-
- The CP starts with some leviathans and sea turtles, and will use the leviathans
- to transport raiding parties ashore. The sea turtles and any trained naval
- units will patrol the shoreline, with occasional incursions into the HP's bay.
-
- 8/19/2002 Added a token economy. Fishing plans not working.
-
- 9/23/2002 Reduced navy size from 17 to 13 on hard. Lowered defend
- army size by 15% on hard.
-
- 9/24/2002 Reduced navy size on easy from 6 to 4, and on moderate from 10 to 7.
-
-
- */
- //==============================================================================
-
-
- include "scn lib.xs";
-
-
- // *****************************************************************************
- //
- // Globals
- //
- // *****************************************************************************
-
- // Attack routes and queries
-
-
-
- // Army control
- int lastAttackPlan = -1; // Used to find "my army" for god power position info
- int defendPlan = -1;
- int navalDefendPlan = -1;
- bool defendOnly = false; // When true, cancels last attack plan, all military go to defense
- int explorePlan = -1; // The naval explore plan
-
- // The following are set in main() based on difficulty level.
- int nextAttackTime = 240000; // Will be adjusted for the wakeup time
- int attackInterval = 240000; // Attack every 4:00
- float attackSize = 6.0;
- float attackMultiplier = 1.2;
- int maxAttackSize = 10;
- float totalArmySize = 25;
- float totalNavySize = 8;
- float standardDelay = 30;
-
-
- int maintainID1 = -1; // Maintain plan for primary military unit
- int maintainQty1 = 3; // Quantity to maintain
- int maintainUnit1 = cUnitTypeSpearman; // Unit type
- int maintainDelay1 = 30; // Interval between training units
-
- int maintainID2 = -1; // Maintain plan for secondary military unit
- int maintainQty2 = 3; // Quantity to maintain
- int maintainUnit2 = cUnitTypeAnubite; // Unit type
- int maintainDelay2 = 60; // Interval between training units
-
-
- int maintainID3 = -1; // Maintain plan for tertiary military unit
- int maintainQty3 = 3; // Quantity to maintain
- int maintainUnit3 = cUnitTypeKebenit; // Unit type
- int maintainDelay3 = 30; // Interval between training units
-
-
- int maintainID4 = -1; // Maintain plan for quatenary military unit
- int maintainQty4 = 2; // Quantity to maintain
- int maintainUnit4 = cUnitTypeSeaTurtle; // Unit type
- int maintainDelay4 = 60; // Interval between training units
-
-
- int maintainIDScout = -1; // Scout unit
- int maintainQtyScout = -1;
- int maintainUnitScout = -1;
- int maintainDelayScout = -1;
-
-
-
-
- // Cinematic blocks
- const string cbTownCenter = "1422";
- const string cbNavyPatrol1 = "1423";
- const string cbNavyPatrol2 = "1424";
- const string cbNavyPatrol3 = "1425";
- const string cbNavyPatrol4 = "1426";
- const string cbNavyPatrol5 = "1427";
- const string cbBay = "1428";
- const string cbDefendEast = "1435";
- const string cbDefendWest = "1436";
- const string cbMainland = "2028";
- const string cbBeachWest = "2821";
-
-
-
- // Misc.
- int age2Time = 420000; // 7 min....will be adjusted in main() for difficulty
- int age3Time = 960000; // 16 min
- int age4Time = 1620000; // 27 min
- int startTime = -1; // Time of the wakeup() function...will be added to the age times.
-
- // Econ
- int maxVills = 20; // Will scale with difficulty
- int maxFishBoats = 10; // Including one to scout
- float goldPercent = 0.25;
- float woodPercent = 0.25;
- float foodPercent = 0.5;
- int gathererTypeID = -1;
- int fishGatherer = -1;
- int mainBase = -1;
- float mainRadius = 100.0;
- const string cbCenter = "1422";
-
-
-
- // *****************************************************************************
- //
- // FUNCTIONS
- //
- // *****************************************************************************
-
-
- // Called by trigger when the cinematics are done
- void wakeup(int parm=-1)
- {
- static bool alreadyRun = false;
- aiEcho("Wakeup running at "+timeString()+".");
- if (alreadyRun == true)
- return;
- alreadyRun = true;
-
- startTime = xsGetTime();
- age2Time = age2Time + startTime;
- xsEnableRule("goToAge3");
- age3Time = age3Time + startTime; // Adjust for delay in wakeup.
- age4Time = age4Time + startTime;
- nextAttackTime = nextAttackTime + startTime;
-
- xsEnableRule("useTornado");
- xsEnableRule("useAncestors");
- xsEnableRule("useRain");
-
- // Init maintain plans
- if (maintainUnit1 > 0)
- maintainID1 = maintainUnit(maintainUnit1, maintainQty1, cInvalidVector, maintainDelay1);
- if (maintainUnit2 > 0)
- maintainID2 = maintainUnit(maintainUnit2, maintainQty2, cInvalidVector, maintainDelay2);
- if (maintainUnit3 > 0)
- maintainID3 = maintainUnit(maintainUnit3, maintainQty3, cInvalidVector, maintainDelay3);
- if (maintainUnit4 > 0)
- maintainID4 = maintainUnit(maintainUnit4, maintainQty4, cInvalidVector, maintainDelay4);
- if (maintainUnitScout > 0)
- maintainIDScout = maintainUnit(maintainUnitScout, maintainQtyScout, cInvalidVector, maintainDelayScout);
-
- maintainUnit(cUnitTypeLeviathan, 3, cInvalidVector, 1); // Keep a reserve of transports
-
- createSimpleMaintainPlan(gathererTypeID, maxVills, true, mainBase);
-
- // Init low-priority defend plan to manage all extra mil units
- defendPlan =aiPlanCreate("Defend Plan", cPlanDefend);
- if (defendPlan >= 0)
- {
- // vector pointA=gTownLocation;
- // pointA=xsVectorSetX(pointA, xsVectorGetX(gTownLocation)-50.0);
- // vector pointB=gTownLocation;
- // pointB=xsVectorSetZ(pointB, xsVectorGetZ(gTownLocation)-50.0);
-
- aiPlanAddUnitType(defendPlan, cUnitTypeLogicalTypeLandMilitary, 0, 200, 200);
- // aiPlanAddUnitType(defendPlan, cUnitTypeSpearman, 0, 200, 200); // All unassigned mil units, will be overridden (below) for navy
- // aiPlanAddUnitType(defendPlan, cUnitTypeAnubite, 0, 200, 200);
- // aiPlanAddUnitType(defendPlan, cUnitTypeChariotArcher, 0, 200, 200);
- aiPlanSetDesiredPriority(defendPlan, 10); // Way low, below scouting and attack
- aiPlanSetVariableVector(defendPlan, cDefendPlanDefendPoint, 0, kbGetBlockPosition(cbTownCenter));
- aiPlanSetVariableInt(defendPlan, cDefendPlanGatherDistance, 0, 15);
-
- aiPlanSetVariableInt(defendPlan, cDefendPlanRefreshFrequency, 0, 5);
- aiPlanSetNumberVariableValues(defendPlan, cDefendPlanAttackTypeID, 2, true);
- aiPlanSetVariableInt(defendPlan, cDefendPlanAttackTypeID, 0, cUnitTypeUnit);
- aiPlanSetVariableInt(defendPlan, cDefendPlanAttackTypeID, 1, cUnitTypeBuilding);
-
- // Start with a simple 3-point patrol
- aiPlanSetNumberVariableValues(defendPlan, cDefendPlanPatrolWaypoint, 3, true);
- aiPlanSetVariableVector(defendPlan, cDefendPlanPatrolWaypoint, 0, kbGetBlockPosition(cbDefendEast));
- aiPlanSetVariableVector(defendPlan, cDefendPlanPatrolWaypoint, 1, kbGetBlockPosition(cbTownCenter));
- aiPlanSetVariableVector(defendPlan, cDefendPlanPatrolWaypoint, 2, kbGetBlockPosition(cbDefendWest));
- aiPlanSetVariableBool(defendPlan, cDefendPlanPatrol, 0, true);
-
- aiPlanSetVariableFloat(defendPlan, cDefendPlanEngageRange, 0, 40);
-
- aiPlanSetActive(defendPlan);
- }
-
-
- // Init moderate-priority defend plan to manage all naval mil units
- navalDefendPlan =aiPlanCreate("Naval Defend Plan", cPlanDefend);
- if (navalDefendPlan >= 0)
- {
- // vector pointA=gTownLocation;
- // pointA=xsVectorSetX(pointA, xsVectorGetX(gTownLocation)-50.0);
- // vector pointB=gTownLocation;
- // pointB=xsVectorSetZ(pointB, xsVectorGetZ(gTownLocation)-50.0);
-
- // aiPlanAddUnitType(navalDefendPlan, cUnitTypeLogicalTypeNavalMilitary, 0, 200, 200);
- aiPlanAddUnitType(navalDefendPlan, cUnitTypeKebenit, 0, 200, 200); // All navy except transports
- aiPlanAddUnitType(navalDefendPlan, cUnitTypeSeaTurtle, 0, 200, 200);
- // aiPlanAddUnitType(navalDefendPlan, cUnitTypeLeviathan, 0,200, 200); // What the heck, try the levi's, too.
- aiPlanSetDesiredPriority(navalDefendPlan, 60); // Somewhat low, but above land attack plan
- aiPlanSetVariableVector(navalDefendPlan, cDefendPlanDefendPoint, 0, kbGetBlockPosition(cbTownCenter));
-
- aiPlanSetVariableInt(navalDefendPlan, cDefendPlanRefreshFrequency, 0, 5);
- aiPlanSetNumberVariableValues(navalDefendPlan, cDefendPlanAttackTypeID, 2, true);
- aiPlanSetVariableInt(navalDefendPlan, cDefendPlanAttackTypeID, 0, cUnitTypeUnit);
- aiPlanSetVariableInt(navalDefendPlan, cDefendPlanAttackTypeID, 1, cUnitTypeBuilding);
-
- aiPlanSetVariableInt(navalDefendPlan, cDefendPlanGatherDistance, 0, 20);
-
- // Start with a simple 3-point patrol
- aiPlanSetNumberVariableValues(navalDefendPlan, cDefendPlanPatrolWaypoint, 5, true);
- aiPlanSetVariableVector(navalDefendPlan, cDefendPlanPatrolWaypoint, 0, kbGetBlockPosition(cbNavyPatrol1));
- aiPlanSetVariableVector(navalDefendPlan, cDefendPlanPatrolWaypoint, 1, kbGetBlockPosition(cbNavyPatrol2));
- aiPlanSetVariableVector(navalDefendPlan, cDefendPlanPatrolWaypoint, 2, kbGetBlockPosition(cbNavyPatrol3));
- aiPlanSetVariableVector(navalDefendPlan, cDefendPlanPatrolWaypoint, 3, kbGetBlockPosition(cbNavyPatrol4));
- aiPlanSetVariableVector(navalDefendPlan, cDefendPlanPatrolWaypoint, 4, kbGetBlockPosition(cbNavyPatrol5));
- aiPlanSetVariableBool(navalDefendPlan, cDefendPlanPatrol, 0, true);
-
- aiPlanSetVariableFloat(navalDefendPlan, cDefendPlanEngageRange, 0, 40);
-
- aiPlanSetActive(navalDefendPlan);
- }
-
- // xsEnableRule("useSpy");
- xsEnableRule("scout");
- xsEnableRule("attackGenerator");
- xsEnableRule("fishing");
- }
-
- void initMainBase()
- {
- // Nuke bases, add one base to rule them all
- kbBaseDestroyAll(cMyID);
-
- mainBase = kbBaseCreate(cMyID, "Base "+kbBaseGetNextID(), kbGetBlockPosition(cbCenter), mainRadius);
- if (mainBase < 0)
- aiEcho("***** Main base creation failed. *****");
-
- vector baseFront=xsVectorNormalize(kbGetMapCenter()-kbGetBlockPosition(cbCenter)); // Set front
- kbBaseSetFrontVector(cMyID, mainBase, baseFront);
- kbBaseSetMaximumResourceDistance(cMyID, mainBase, mainRadius+50.0); // Gather up to 50m beyond base perimeter
- kbBaseSetMain(cMyID, mainBase, true); // Make this the main base
-
- // Add the buildings
- int buildingQuery = -1;
- int count = 0;
- buildingQuery = kbUnitQueryCreate("Building Query"); // All buildings in the base
- configQuery(buildingQuery, cUnitTypeBuilding, -1, cUnitStateAliveOrBuilding, cMyID, kbGetBlockPosition(cbCenter), false, mainRadius);
- kbUnitQueryResetResults(buildingQuery);
- count = kbUnitQueryExecute(buildingQuery);
-
- int i = 0;
- int buildingID = -1;
- for (i=0; < count)
- {
- buildingID = kbUnitQueryGetResult(buildingQuery, i);
- // Add it to the base
- kbBaseAddUnit( cMyID, mainBase, buildingID );
- }
- }
-
-
- void initEcon()
- {
- //-- get our fish gatherer.
- fishGatherer = kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionFish,0);
- gathererTypeID = kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionGatherer,0);
-
- aiSetAutoGatherEscrowID(cRootEscrowID);
- aiSetAutoFarmEscrowID(cRootEscrowID);
-
- int herdPlanID=aiPlanCreate("GatherHerdable Plan", cPlanHerd);
- if (herdPlanID >= 0)
- {
- aiPlanAddUnitType(herdPlanID, cUnitTypeHerdable, 0, 100, 100);
- aiPlanSetVariableInt(herdPlanID, cHerdPlanBuildingTypeID, 0, cUnitTypeSettlementLevel1);
- aiPlanSetActive(herdPlanID);
- }
-
- aiSetResourceGathererPercentageWeight(cRGPScript, 1);
- aiSetResourceGathererPercentageWeight(cRGPCost, 0);
-
- kbSetAICostWeight(cResourceFood, 1.0);
- kbSetAICostWeight(cResourceWood, 0.7);
- kbSetAICostWeight(cResourceGold, 0.8);
- kbSetAICostWeight(cResourceFavor, 7.0);
-
- aiSetResourceGathererPercentage(cResourceFood, foodPercent, false, cRGPScript);
- aiSetResourceGathererPercentage(cResourceWood, woodPercent, false, cRGPScript);
- aiSetResourceGathererPercentage(cResourceGold, goldPercent, false, cRGPScript);
- aiSetResourceGathererPercentage(cResourceFavor, 0.0, false, cRGPScript);
- aiNormalizeResourceGathererPercentages(cRGPScript);
-
- //bool aiSetResourceBreakdown( int resourceTypeID, int resourceSubTypeID, int numberPlans, int planPriority, float percentage, int baseID )
- // aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeEasy, numFoodEasyPlans, 50, 1.0, gMainBaseID);
- // aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeHuntAggressive, numFoodHuntAggressivePlans, 100, 1.0, gMainBaseID);
- aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeFish, 1, 50, 1.0, mainBase);
- aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeFarm, 1, 50, 1.0, mainBase);
- aiSetResourceBreakdown(cResourceWood, cAIResourceSubTypeEasy, 1, 50, 1.0, mainBase);
- aiSetResourceBreakdown(cResourceGold, cAIResourceSubTypeEasy, 1, 50, 1.0, mainBase);
- // aiSetResourceBreakdown(cResourceFavor, cAIResourceSubTypeEasy, numFavorPlans, 50, 1.0, gMainBaseID);
- }
-
-
-
-
-
- // Called via trigger, cancel last offensive plan and put all units on defense.
- void defend(int parm=-1)
- {
- aiEcho("Defend function called.");
- defendOnly = true;
- aiPlanDestroy(lastAttackPlan);
- }
-
-
-
-
- // Used to delete units that are being replaced by a new type.
- void deleteObsoleteUnits(int unitType=cUnitTypeUnit, int player=2, vector center=vector(-1,-1,-1), float radius = 20.0, float percent=1.00)
- {
- // Make query
- int query = -1;
- int count = -1;
-
- query = kbUnitQueryCreate("Unit deletion query");
- if ( configQuery(query, unitType, -1, cUnitStateAlive, player, center, false, radius) == false)
- return;
- kbUnitQueryResetResults(query);
- count = kbUnitQueryExecute(query);
-
- // Iterate list, deleting percentage indicated
- float remainder=0.0; // Used to handle percentages, when this gets >= 1, it's time to delete a unit.
-
- for (i=0; <count)
- {
- remainder = remainder + percent;
- if (remainder >= 1.0) // time to delete one
- {
- aiTaskUnitDelete(kbUnitQueryGetResult(query,i));
- remainder = remainder - 1.0;
- }
- }
- }
-
-
- void age2EventHandler(int bogus=-1)
- {
- xsEnableRule("goToAge3");
- xsEnableRule("getAge2UnitUpgrades");
- xsEnableRule("getAge2ArmoryUpgrades");
-
-
-
- // xsEnableRule("useUndermine");
-
- }
-
-
-
- void age3EventHandler(int bogus=-1)
- {
-
- if (age4Time > 0) // May be suppressed for difficulty
- xsEnableRule("goToAge4");
- xsEnableRule("getAge3UnitUpgrades");
- xsEnableRule("getAge3ArmoryUpgrades");
-
-
- // aiPlanSetVariableInt(navyMaintainID, cTrainPlanUnitType, 0, navyUnit);
- // if (navyUnit != oldUnit)
- // {
- // deleteObsoleteUnits(oldUnit, 2, kbGetBlockPosition(cbFinalGate), 50, .5); // Delete half of the old units
- // aiEcho("Deleting units: "+kbGetProtoUnitName(oldUnit));
- // }
-
- // xsEnableRule("useFlamingWeapons");
- }
-
-
-
- void age4EventHandler(int bogus=-1)
- {
- xsEnableRule("getAge4UnitUpgrades");
- xsEnableRule("getAge4ArmoryUpgrades");
-
-
-
-
- //xsEnableRule("useNidhogg");
- }
-
-
-
-
- void attack(int size=0)
- {
- if (defendOnly == true)
- return;
-
- int attackID=aiPlanCreate("Attack at "+timeString(true)+" ", cPlanAttack);
- if (attackID < 0)
- return;
-
- if (aiPlanSetVariableInt(attackID, cAttackPlanPlayerID, 0, 1) == false)
- return;
-
- if (aiPlanSetNumberVariableValues(attackID, cAttackPlanTargetTypeID, 3, true) == false)
- return;
-
- aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
- aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding);
- aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 2, cUnitTypeAbstractWall);
-
- // Specify other continent so that armies will transport
- aiPlanSetNumberVariableValues( attackID, cAttackPlanTargetAreaGroups, 1, true);
- aiEcho("Area group for mainland is "+kbAreaGroupGetIDByPosition(kbGetBlockPosition(cbMainland)));
- aiPlanSetVariableInt(attackID, cAttackPlanTargetAreaGroups, 0, kbAreaGroupGetIDByPosition(kbGetBlockPosition(cbMainland)));
-
- aiPlanSetVariableVector(attackID, cAttackPlanGatherPoint, 0, kbGetBlockPosition(cbTownCenter));
- aiPlanSetVariableFloat(attackID, cAttackPlanGatherDistance, 0, 20.0);
-
- switch(kbGetAge()) // Set the targets and unit composition
- {
- case cAge1:
- {
- aiPlanAddUnitType(attackID, cUnitTypeLogicalTypeLandMilitary, 1, size, size);
- break;
- }
- case cAge2:
- {
- aiPlanAddUnitType(attackID, cUnitTypeLogicalTypeLandMilitary, 1, size, size);
- break;
- }
- case cAge3:
- {
- aiPlanAddUnitType(attackID, cUnitTypeSpearman, 1, (4*size)/5, (4*size)/5);
- aiPlanAddUnitType(attackID, cUnitTypeMythUnit, 1, 1+size/5, 1+size/5);
- break;
- }
- case cAge4:
- {
- aiPlanAddUnitType(attackID, cUnitTypeSpearman, 1, (4*size)/5, (4*size)/5);
- aiPlanAddUnitType(attackID, cUnitTypeMythUnit, 1, 1+size/5, 1+size/5);
- break;
- }
- }
-
- aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbTownCenter));
- aiPlanSetRequiresAllNeedUnits(attackID, false);
- aiPlanSetDesiredPriority(attackID, 50); // Less than scouting, more than defense
- aiPlanSetActive(attackID);
- aiEcho("Activating attack plan "+attackID+" with appx "+size+" units.");
- lastAttackPlan = attackID; // update the global var
- }
-
-
-
-
-
-
- void main()
- {
- aiEcho("Starting Scn20p2.xs");
-
- //Calculate some areas.
- kbAreaCalculate(1200.0);
- aiRandSetSeed();
- kbSetTownLocation(kbGetBlockPosition(cbTownCenter));
- aiSetAttackResponseDistance(20.0);
-
- aiSetAgeEventHandler(cAge2, "age2EventHandler");
- aiSetAgeEventHandler(cAge3, "age3EventHandler");
- aiSetAgeEventHandler(cAge4, "age4EventHandler");
-
- kbEscrowSetPercentage( cEconomyEscrowID, cAllResources, 0.0);
- kbEscrowSetPercentage( cMilitaryEscrowID, cAllResources, 0.0);
- kbEscrowAllocateCurrentResources();
-
- aiEcho("Difficulty = "+aiGetWorldDifficulty());
-
- switch(aiGetWorldDifficulty()) // Set up the attack control and age-up parameters
- {
- case 0: // Easy
- {
- nextAttackTime = 300000; // 5 min
- attackInterval = 240000; // 4 min
- attackSize = 2.0;
- attackMultiplier = 1.1; // 10% per 4 min
- maxAttackSize = 7;
- totalArmySize = 10;
- totalNavySize = 4;
- standardDelay = 90;
- age2Time = 900000; // 15 min
- age3Time = 1800000; // 30 min
- age4Time = -1; // Not permitted
- break;
- }
- case 1: // Moderate
- {
- nextAttackTime = 240000;
- attackInterval = 240000;
- attackSize = 3.0;
- attackMultiplier = 1.2; // 20% per 4 min
- maxAttackSize = 15;
- totalArmySize = 20;
- totalNavySize = 7;
- standardDelay = 60;
- age2Time = 600000; // 10 min
- age3Time = 900000; // 15 min
- age4Time = 1800000; // 30 min
- break;
- }
- case 2: // Difficult
- {
- nextAttackTime = 120000;
- attackInterval = 138000;
- attackSize = 5.0;
- attackMultiplier = 1.3; // 30% per 3 min
- maxAttackSize = 30;
- totalArmySize = 34;
- totalNavySize = 13;
- standardDelay = 30;
- age2Time = 420000; // 7 min
- age3Time = 600000; // 10 min
- age4Time = 1200000; // 20 min
- break;
- }
- case 3: // Nightmare
- {
- nextAttackTime = 60000;
- attackInterval = 120000;
- attackSize = 6.0;
- attackMultiplier = 1.3; // 30% per 2 min
- maxAttackSize = 45;
- totalArmySize = 60;
- totalNavySize = 25;
- standardDelay = 20;
- age2Time = 240000; // 4 min
- age3Time = 300000; // 5 min
- age4Time = 600000; // 10 min
- break;
- }
- }
-
- maintainDelay1 = standardDelay/3; // Interval between training units
- maintainQty1 = totalArmySize/2;
- maintainDelay2 = standardDelay;
- maintainQty2 = 1 + (totalArmySize/6);
- maintainDelay3 = standardDelay;
- maintainQty3 = 2*(totalNavySize/3);
- maintainDelay4 = 4*standardDelay;
- maintainQty4 = 1 + (totalNavySize/3);
- maintainUnit(cUnitTypeChariotArcher, (totalArmySize/3), cInvalidVector, (standardDelay/2));
-
-
- initMainBase();
- initEcon();
- }
-
-
-
-
-
-
-
- // *****************************************************************************
- //
- // RULES
- //
- // *****************************************************************************
-
- rule scout
- inactive
- minInterval 5
- {
- // just set up an explore plan
- explorePlan = aiPlanCreate("Explore", cPlanExplore);
- if(explorePlan >= 0)
- {
- aiPlanSetVariableFloat( explorePlan, cExplorePlanLOSMultiplier, 0, 4.0 );
- aiPlanAddUnitType(explorePlan, cUnitTypeKebenit, 1, 1, 1);
- aiPlanSetDesiredPriority(explorePlan, 90);
- aiPlanSetActive(explorePlan);
- }
- xsDisableSelf();
- }
-
-
- rule fishing
- minInterval 30
- inactive
- {
- //-- get our fish gatherer.
- fishGatherer = kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionFish,0);
-
- if (maxFishBoats > 0)
- createSimpleMaintainPlan(fishGatherer, maxFishBoats, true, mainBase);
-
- if (maxFishBoats < 2)
- {
- // At most, just a scout
- xsDisableSelf();
- return;
- }
- //-- Get the closest water area. if there isn't one, we can't fish.
- static int areaID = -1;
- if(areaID == -1)
- areaID = kbAreaGetClosetArea(kbGetBlockPosition(cbCenter), cAreaTypeWater);
-
- // if( kbSetupForResource(mainBase, cResourceWood, 25.0, 600) == false)
- // return;
-
-
- //-- Create the fish plan.
- int fishPlanID=aiPlanCreate("FishPlan", cPlanFish);
- if (fishPlanID >= 0)
- {
- aiEcho("Starting up the fishing plan. Will fish when I find fish.");
- aiPlanSetDesiredPriority(fishPlanID, 70);
- aiPlanSetVariableVector(fishPlanID, cFishPlanLandPoint, 0, kbGetBlockPosition(cbCenter));
- //-- If you don't explicitly set the water point, the plan will find one for you.
- aiPlanSetVariableBool(fishPlanID, cFishPlanAutoTrainBoats, 0, false); // I'm going to have a maintain plan for fishing + scouting combined
- aiPlanSetEscrowID(fishPlanID, cRootEscrowID);
- aiPlanSetVariableFloat(fishPlanID, cFishPlanMaximumDockDist, 0, 500.0);
- aiPlanAddUnitType(fishPlanID, fishGatherer, 1, maxFishBoats-1, maxFishBoats-1);
- aiPlanSetActive(fishPlanID);
- }
-
-
-
- /*
- // Add a fish boat explore plan
- int exploreWaterID = aiPlanCreate("Water Explore", cPlanExplore);
- if(exploreWaterID >= 0)
- {
- //aiPlanAddVariableFloat( exploreID, cExplorePlanLOSMultiplier, "LOS Multiplier", 1);
- aiPlanSetVariableFloat( exploreWaterID, cExplorePlanLOSMultiplier, 0, 4.0 );
- aiPlanAddUnitType(exploreWaterID, fishGatherer, 1, 1, 1);
- aiPlanSetDesiredPriority(exploreWaterID, 90);
- aiPlanSetActive(exploreWaterID);
- }
- */
-
- xsDisableSelf();
- }
-
-
-
-
-
-
- rule goToAge2
- inactive
- minInterval 10
- {
- if ( xsGetTime() < age2Time)
- return;
- researchTech(cTechAge2Heimdall);
- xsDisableSelf();
- }
-
-
-
- rule goToAge3
- inactive
- mininterval 20
- {
- if ( xsGetTime() < age3Time )
- return;
- researchTech(cTechAge3Nephthys);
- xsDisableSelf();
- }
-
-
- rule goToAge4
- inactive
- mininterval 20
- {
- if ( xsGetTime() < age4Time )
- return;
- researchTech(cTechAge4Thoth);
- xsDisableSelf();
- }
-
-
-
- rule getAge2UnitUpgrades
- inactive
- minInterval 20
- {
- if ( xsGetTime() < (age2Time + age2Time + age3Time)/3 )
- return; // Wait till 1/3 to age3
- researchTech(cTechMediumInfantry);
- researchTech(cTechMediumCavalry);
- xsDisableSelf();
- }
-
- rule getAge2ArmoryUpgrades
- inactive
- {
- if ( xsGetTime() < (age2Time + age3Time + age3Time)/3 )
- return; // Wait till 2/3 to age3
- aiEcho("Getting age 2 armory upgrades");
- researchTech(cTechCopperWeapons);
- researchTech(cTechCopperMail);
- researchTech(cTechCopperShields);
- xsDisableSelf();
- }
-
- rule getAge3UnitUpgrades
- inactive
- {
- if ( xsGetTime() < (age3Time+180000) )
- return;
- researchTech(cTechHeavyInfantry);
- researchTech(cTechHeavyCavalry);
- xsDisableSelf();
- }
-
- rule getAge3ArmoryUpgrades
- inactive
- {
- if ( xsGetTime() < (age3Time+300000) )
- return;
- researchTech(cTechBronzeWeapons);
- researchTech(cTechBronzeMail);
- researchTech(cTechBronzeShields);
- xsDisableSelf();
- }
-
- rule getAge4UnitUpgrades
- inactive
- {
- if ( xsGetTime() < (age4Time+300000) )
- return;
- researchTech(cTechChampionInfantry);
- researchTech(cTechChampionCavalry);
- xsDisableSelf();
- }
-
- rule getAge4ArmoryUpgrades
- inactive
- {
- if ( xsGetTime() < (age4Time+600000) )
- return;
- researchTech(cTechIronWeapons);
- researchTech(cTechIronMail);
- researchTech(cTechIronShields);
- xsDisableSelf();
- }
-
- rule favorGenerator
- active
- {
- aiResourceCheat( 2, cResourceFavor, 100.0 ); // Max out the favor every 15 seconds
- kbEscrowAllocateCurrentResources(); // Make sure the escrow knows about it.
- }
-
-
- rule attackGenerator
- minInterval 10
- inactive
- {
- //aiEcho("attack check running, next time is "+nextAttackTime);
- if ( xsGetTime() < nextAttackTime )
- return;
-
- attack(attackSize);
- nextAttackTime = xsGetTime() + attackInterval;
- attackSize = attackSize * attackMultiplier;
- if (attackSize > maxAttackSize)
- attackSize = maxAttackSize;
- aiEcho("Next attack size will be "+attackSize+".");
- }
-
-
- rule useTornado // Drop a tornado if we see enemy navy/fishing units near my water scout, unless its near the bay.
- minInterval 5
- inactive
- {
- // look for a group of 4 enemy units at my water scout's location
- int targetUnit = -1;
- int fishBoatCount = -1;
- int enemyCount = -1;
-
- vector pVec = aiPlanGetLocation(explorePlan);
- if (xsVectorGetX(pVec)<0)
- return;
-
- static int tempQuery = -1;
- if (tempQuery < 0)
- { // Doesn't exist, set it up
- tempQuery = kbUnitQueryCreate("useTornado");
-
- if ( configQuery(tempQuery, cUnitTypeUtilityShip, -1, cUnitStateAlive, 1, pVec, true, 50) == false)
- return;
- }
- else
- {
- kbUnitQuerySetUnitType(tempQuery, cUnitTypeUtilityShip);
- kbUnitQuerySetPosition(tempQuery, pVec);
- }
-
- kbUnitQueryResetResults(tempQuery);
- fishBoatCount = kbUnitQueryExecute(tempQuery);
-
- kbUnitQuerySetUnitType(tempQuery, cUnitTypeLogicalTypeNavalMilitary);
- enemyCount = kbUnitQueryExecute(tempQuery); // Add military units to fish boat list
- if (enemyCount < 4)
- return;
-
- aiEcho("Tornado: Fish boats = "+fishBoatCount+", Total units = "+enemyCount);
- targetUnit = kbUnitQueryGetResult(tempQuery, enemyCount/2); // grab middle unit
-
- // confirm LOS
-
- if ( kbUnitVisible(targetUnit) != true )
- {
- aiEcho("Don't have LOS to unit "+targetUnit);
- return;
- }
-
- // Check proximity to the bay via cbBay marker
- bool tooClose = true; // Set it false if dx or dz > 50
- vector target = cInvalidVector;
- vector bay = cInvalidVector;
-
- target = kbUnitGetPosition(targetUnit);
- bay = kbGetBlockPosition(cbBay);
-
- float dx = 0.0;
- float dz = 0.0;
-
- dx = xsVectorGetX(target) - xsVectorGetX(bay);
- dz = xsVectorGetZ(target) - xsVectorGetZ(bay);
- aiEcho("dx = "+dx+", dz = "+dz);
-
- if (dx < -50.0)
- tooClose = false;
- if (dx > 50.0)
- tooClose = false;
- if (dz < -50.0)
- tooClose = false;
- if (dz > 50.0)
- tooClose = false;
-
- if (tooClose == true)
- {
- aiEcho("Can't use tornado, too close to the bay.");
- return;
- }
-
- aiEcho("Using Tornado");
- if ( aiCastGodPowerAtPosition(cTechTornado, target) == true)
- xsDisableSelf();
- else
- aiEcho("Tornado failed at "+target);
- }
-
-
-
- rule useAncestors // Use ancestors if there are >= 6 naval units near the cineblock on the beach.
- minInterval 5
- inactive
- {
- // look for a group of 6 enemy naval units at my water scout's location
- int targetUnit = -1;
-
- int enemyCount = -1;
-
-
- static int tempQuery = -1;
- if (tempQuery < 0)
- { // Doesn't exist, set it up
- tempQuery = kbUnitQueryCreate("useAncestors");
-
- if ( configQuery(tempQuery, cUnitTypeLogicalTypeNavalMilitary, -1, cUnitStateAlive, 1, kbGetBlockPosition(cbBeachWest), true, 50) == false)
- return;
- }
-
-
- kbUnitQueryResetResults(tempQuery);
- enemyCount = kbUnitQueryExecute(tempQuery); // Get the count
- if (enemyCount < 6)
- return;
-
- targetUnit = kbUnitQueryGetResult(tempQuery, enemyCount/2); // grab middle unit
-
- // confirm LOS
-
- if ( kbUnitVisible(targetUnit) != true )
- {
- aiEcho("Don't have LOS to unit "+targetUnit);
- return;
- }
-
-
-
- aiEcho("Using Ancestors");
- if ( aiCastGodPowerAtPosition(cTechSkeletonPower, kbUnitGetPosition(targetUnit)) == true)
- xsDisableSelf();
- else
- aiEcho("Ancestors failed at "+kbUnitGetPosition(targetUnit));
- }
-
-
-
- rule useRain
- minInterval 5
- inactive
- { // 10 minutes after wakeup()
- static int rainTime = 0;
-
- if (rainTime == 0)
- rainTime = xsGetTime()+10*60*1000;
-
- if (xsGetTime() < rainTime)
- return;
-
- aiCastGodPowerAtPosition(cTechRain, kbGetBlockPosition(cbTownCenter));
- xsDisableSelf();
- }
-
-